#[cfg(windows)]
extern crate winapi;
use winapi::um::errhandlingapi::GetLastError;

use winapi::um::winbase::FormatMessageA;
use winapi::um::wincrypt::CryptAcquireContextA;
use winapi::um::wincrypt::CryptGetProvParam;
use winapi::um::wincrypt::CryptReleaseContext;
use winapi::um::wincrypt::CRYPT_VERIFYCONTEXT;
use winapi::um::wincrypt::PP_NAME;

use winapi::um::wincrypt::HCRYPTPROV;
use winapi::um::wincrypt::PROV_RSA_FULL;

use winapi::shared::minwindef::BOOL;
use winapi::shared::minwindef::DWORD;
use winapi::um::winnt::{
    LANG_ENGLISH, MAKELANGID, SUBLANG_ENGLISH_US,
};

use winapi::um::winbase::{
    FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_FROM_SYSTEM,
};


use std::ffi::CString;


// CSP(加密服务提供商名称)
const PROVIDER_NAME: &str = "EnterSafe ePass3000GM CSP v1.0";

/// @Author: DengLibin
/// @Date: Create in 2024-01-17 18:25:56
/// @Description: 访问csp接口
#[cfg(windows)]
pub fn hello_csp() {
    let mut sz_provider = PROVIDER_NAME.as_bytes().to_vec();
    //加一个0结尾
    sz_provider.push(0);


    //转i8
    let mut provider_str = sz_provider
        .iter()
        .map(|item| *item as i8)
        .collect::<Vec<i8>>();
    let provider = provider_str.as_mut_ptr();
    //清理
    drop(sz_provider);
    unsafe {
        let r = CString::from_raw(provider).into_string();
        match r {
            Ok(s) =>{
                println!("服务体提供商:{}", s);
            },
            Err(e)=>{
                println!("服务体提供商错误：{}", e);
            }
        }
        // 定义加密上下文句柄
        let mut hprov: HCRYPTPROV = 0;
        let hp = &mut hprov;
        //获取上下文句柄
        let b: BOOL = CryptAcquireContextA(
            hp,
            std::ptr::null(),
            provider,
            PROV_RSA_FULL,
            CRYPT_VERIFYCONTEXT,
        );
        println!("初始化上下文结果：{},句柄:{}", b, hprov);

        let mut data_len: DWORD = 1024;
        let data_len_p = &mut data_len;

        // 成功
        if b != 0 {
            let mut pb_data: Vec<u8> = vec![0; 1024];
            let pd_data_p = pb_data.as_mut_ptr();
            //获取csp名称
            let param_b: BOOL = CryptGetProvParam(hprov, PP_NAME, pd_data_p, data_len_p, 0);
            println!("获取结果:{}", param_b);
            println!("csp名称:{}", String::from_utf8(pb_data).unwrap());

            let b: BOOL = CryptReleaseContext(hprov, 0);
            println!("释放结果:{}", b);
        } else {
            //show_error();
            println!("usbkey未插入");
        }
    }
}

#[allow(dead_code)]
fn show_error() {
    unsafe {
        let error_code = GetLastError();
        println!("错误码:{0:#x}", error_code);

        let mut buffer = vec![0; 100];
        let buf_p = buffer.as_mut_ptr();
        let dw_language_id = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) as u32;
        //MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) as u32
        let r = FormatMessageA(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            core::ptr::null_mut(),
            0x80090019,
            dw_language_id,
            buf_p,
            0,
            core::ptr::null_mut(),
        );
        println!("错误:r={}", r);
        let mut v = vec![];
        for i in 0..r {
            print!("{},", buffer[i as usize]);
            v.push(buffer[i as usize]);
        }

    
    }
}

